Runxi Yu’s Personal Forge
Login

melonsurvey

Web survey software for melons
Commit info
ID
cc8979e6f5fd6a1c5a8bc6d776daa26cb3df9466
Author
Runxi Yu <me@runxiyu.org>
Author date
Thu, 10 Apr 2025 23:12:30 +0800
Committer
Runxi Yu <me@runxiyu.org>
Committer date
Thu, 10 Apr 2025 23:12:30 +0800
Actions
Table updates
package main

import (
	"embed"
	"encoding/csv"
	"encoding/json"
	"fmt"
	"io/fs"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
)

//go:embed static/*
var embeddedStatic embed.FS

func main() {
	fs, err := fs.Sub(embeddedStatic, "static")
	if err != nil {
		panic(err)
	}

	http.Handle("/", http.FileServer(http.FS(fs)))
	http.HandleFunc("/submit", handleForm)
	http.HandleFunc("/responses.csv", serveCSV)

	if err := os.MkdirAll("responses", 0755); err != nil {
		log.Fatalf("unable to create responses folder: %v", err)
	}

	log.Println("listening 127.0.0.1:9074")
	log.Fatal(http.ListenAndServe("127.0.0.1:9074", nil))
}

func handleForm(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
		return
	}

	if err := r.ParseForm(); err != nil {
		http.Error(w, "Unable to parse form", http.StatusBadRequest)
		return
	}

	data := make(map[string]string)
	for key, values := range r.PostForm {
		if len(values) > 0 {
			data[key] = values[0]
		} else {
			data[key] = ""
		}
	}

	ip := r.Header.Get("X-Forwarded-For")
	if ip != "" {
		ip = strings.Split(ip, ",")[0]
		ip = strings.TrimSpace(ip)
	} else {
		ip, _, _ = net.SplitHostPort(r.RemoteAddr)
	}
	data["ip_address"] = ip

	filename := time.Now().Format("20060102_150405.000") + ".json"
	filePath := filepath.Join("responses", filename)

	file, err := os.Create(filePath)
	if err != nil {
		http.Error(w, "无法打开保存文件:"+err.Error(), http.StatusInternalServerError)
		return
	}
	defer file.Close()

	encoder := json.NewEncoder(file)
	encoder.SetIndent("", "\t")
	if err := encoder.Encode(data); err != nil {
		http.Error(w, "无法写入保存文件:"+err.Error(), http.StatusInternalServerError)
		return
	}

	fmt.Fprintf(w, "感谢您的提交!您的数据已成功保存。")
	fmt.Fprintf(w, `恭喜您完成所有测试并衷心感谢您的参与!
如有兴趣了解实验数据分析结果,请关注微信公众号 @WIT studio。`)
}

func serveCSV(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/csv")
	w.Header().Set("Content-Disposition", "attachment;filename=responses.csv")

	writer := csv.NewWriter(w)
	defer writer.Flush()

	fieldOrder := []string{
		"gender", "age", "dialect", "wuyu_details", "guanhua_details", "other_details",
		"usage_frequency", "fluency", "foreign_language", "music_training",
		"absolute_pitch", "music_freq",
	}
	for i := 1; i <= 20; i++ {
		fieldOrder = append(fieldOrder, fmt.Sprintf("q%d", i))
	}
	fieldOrder = append(fieldOrder, "cadence1", "cadence2", "cadence3", "cadence4")
	fieldOrder = append(fieldOrder,
		"style1trap", "style2drill", "style3drumbass", "style4reggaetton", "style5rb",
	)

	if err := writer.Write(fieldOrder); err != nil {
		http.Error(w, "Failed to write header", http.StatusInternalServerError)
		return
	}

	files, err := os.ReadDir("responses")
	if err != nil {
		http.Error(w, "Failed to read responses", http.StatusInternalServerError)
		return
	}

	sort.Slice(files, func(i, j int) bool {
		return files[i].Name() < files[j].Name()
	})

	for _, file := range files {
		if !strings.HasSuffix(file.Name(), ".json") {
			continue
		}
		path := filepath.Join("responses", file.Name())

		f, err := os.Open(path)
		if err != nil {
			log.Printf("Failed to open file %s: %v", path, err)
			continue
		}

		var data map[string]string
		if err := json.NewDecoder(f).Decode(&data); err != nil {
			log.Printf("Failed to decode %s: %v", path, err)
			f.Close()
			continue
		}
		f.Close()

		var row []string
		for _, key := range fieldOrder {
			row = append(row, data[key])
		}
		if err := writer.Write(row); err != nil {
			log.Printf("Failed to write row: %v", err)
		}
	}
}
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<title>方言背景对音乐感知与音乐学习能力的影响:实验问卷</title>
	<style>
		body {
			font-family: Arial, sans-serif;
			background-color: #f8f8f8;
			color: #333;
			line-height: 1.6;
			margin: 0;
			padding: 0 15px;
		}
		h1, h2 {
			color: #2c3e50;
		}
		form {
			background-color: #fff;
			padding: 20px;
			margin: 20px auto;
			max-width: 900px;
			box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
			border-radius: 5px;
		}
		p {
			margin-bottom: 10px;
		}
		label {
			display: inline-block;
			margin: 5px 0;
		}
		input[type="text"] {
			margin-left: 5px;
			padding: 5px;
			width: 150px;
		}
		audio {
			display: inline-block;
			border-radius: 0;
			vertical-align: middle;
			padding: 0px;
			border: 0;
			background-color: #fff;
			color: black;
		}
		ol {
			padding-left: 20px;
		}
		ol li {
			margin-bottom: 20px;
		}
		button[type="submit"] {
			background-color: #3498db;
			color: white;
			border: none;
			padding: 10px 20px;
			font-size: 16px;
			border-radius: 4px;
			cursor: pointer;
			margin-top: 20px;
		}
		button[type="submit"]:hover {
			background-color: #2980b9;
		}
		br {
			line-height: 1.5;
		}
		table {
			border-collapse: collapse;
			margin: 20px 0;
			font-size: 16px;
			background-color: #fff;
		}
		table th,
		table td {
			border: 1px solid #ddd;
			padding: 0px 0.75rem;
			vertical-align: middle;
		}
		table td audio {
			margin: 0;
		}
		table td:has(audio:only-child), table td:has(input:only-child) {
			padding: 0;
		}
		table td input[type="text"]:only-child {
			margin: 0;
			border: 0;
			height: 100%;
		}
		table td label:only-child {
			margin: 0rem 0.5rem;
		}
		input[name="section"], input[name="show-all-pages"] {
			display: none;
		}
		
		.page {
			display: none;
		}
		
		#page0:checked ~ .form-wrapper form .page0,
		#page1:checked ~ .form-wrapper form .page1,
		#page2:checked ~ .form-wrapper form .page2,
		#page3:checked ~ .form-wrapper form .page3 {
			display: block;
		}
		
		#show-all-pages:checked ~ .form-wrapper form .page {
			display: block !important;
		}
		
		#show-all-pages:checked ~ .form-wrapper form .pagination-buttons {
			display: none !important;
		}

		#show-all-pages:checked ~ .form-wrapper .show-all-pages-label {
			background-color: #3498db;
			color: #fff;
			padding: 3px 6px;
			border-radius: 4px;
			cursor: pointer;
		}
		
		.show-all-pages-label {
			background-color: #ecf0f1;
			color: #2c3e50;
			padding: 3px 6px;
			border-radius: 4px;
			cursor: pointer;
		}

		.pagination-buttons > label {
			background-color: #3498db;
			color: #fff;
			padding: 3px 6px;
			border-radius: 4px;
			cursor: pointer;
		}
	</style>
	<script>
		document.addEventListener('DOMContentLoaded', () => {
			document.querySelectorAll('audio.once').forEach(audio => {
				audio.addEventListener('play', function handler() {
					audio.removeEventListener('play', handler);
					audio.onplay = e => {
						e.preventDefault();
						audio.pause();
						audio.currentTime = 0;
		
						const warning = document.createElement('div');
						warning.textContent = '不能重复播放';
		
						audio.replaceWith(warning);
					};
				});
			});
			document.querySelectorAll('.pagination-buttons > label').forEach(label => {
				label.addEventListener('click', () => {
					document.getElementById('scroll-target').scrollIntoView({
						block: 'start'
					});
				});
			});
		});
	</script>
</head>
<body>
	<input type="checkbox" name="show-all-pages" id="show-all-pages">
	<input type="radio" name="section" id="page0" checked>
	<input type="radio" name="section" id="page1">
	<input type="radio" name="section" id="page2">
	<input type="radio" name="section" id="page3">
	<div class="form-wrapper">
	<form method="post" action="submit">
	<h1>方言背景对音乐感知与音乐学习能力的影响:实验问卷</h1>
	<p>您好!非常感谢您抽出宝贵时间参加本实验。</p>
	<p>填写此份问卷即说明您同意将以下个人信息和测试得分作为实验数据供后续分析。我们将不会泄露您的个人信息。</p>
	<p>为了音频能顺利播放,请使用电脑浏览器打开问卷链接。</p>
	<p>如您在测试过程中感到不适可随时退出,您的数据将不会被记录。</p>
	<p>感谢您的配合!</p>
	<label for="show-all-pages" class="show-all-pages-label">显示所有页面</label>
	<span id="scroll-target"></span>
	<div class="page page0">

		<p>您的性别?</p>
		<label><input type="radio" name="gender" value="男"> 男</label>
		<label><input type="radio" name="gender" value="女"> 女</label>
		<label><input type="radio" name="gender" value="其他"> 其他</label>

		<p>您的年龄段?</p>
		<label><input type="radio" name="age" value="18岁以下" required> 18 岁以下</label>
		<label><input type="radio" name="age" value="18~25" required> 18&ndash;25</label>
		<label><input type="radio" name="age" value="26~30" required> 26&ndash;30</label>
		<label><input type="radio" name="age" value="31~40" required> 31&ndash;40</label>
		<label><input type="radio" name="age" value="41~50" required> 41&ndash;50</label>
		<label><input type="radio" name="age" value="51~60" required> 51&ndash;60</label>
		<label><input type="radio" name="age" value="60以上" required> 60以上</label>

		<p>您的母语方言是?只要您家中使用除标准普通话以外的方言,就填写相应的方言。如果完全不使用方言,填写“普通话”。</p>
		<label><input type="radio" name="dialect" value="吴语" required> 吴语(江南地区,以上海话、苏州话、杭州话为代表) <input type="text" name="wuyu_details"></label><br>
		<label><input type="radio" name="dialect" value="粤语" required> 粤语(广东、广西皆有分布,以广府粤语为代表)</label><br>
		<label><input type="radio" name="dialect" value="官话" required> 官话(普通话/江淮/西南/中原/东北...)<input type="text" name="guanhua_details"></label><br>
		<label><input type="radio" name="dialect" value="其他" required> 其他(如闽/湘/赣/客家) <input type="text" name="other_details"></label>

		<p>您使用方言的频率是? </p>
		<label><input type="radio" name="usage_frequency" value="每天使用" required> 每天使用</label><br>
		<label><input type="radio" name="usage_frequency" value="每周使用1-5次" required> 每周使用 1&ndash;5 次</label><br>
		<label><input type="radio" name="usage_frequency" value="每月使用1-5次" required> 每月使用 1&ndash;5 次</label><br>
		<label><input type="radio" name="usage_frequency" value="几乎不使用" required> 几乎不使用</label>

		<p>您认为自己的方言流利程度是?</p>
		<label><input type="radio" name="fluency" value="1" required> 1 听得懂但不会说</label>
		<label><input type="radio" name="fluency" value="2" required> 2</label>
		<label><input type="radio" name="fluency" value="3" required> 3</label>
		<label><input type="radio" name="fluency" value="4" required> 4</label>
		<label><input type="radio" name="fluency" value="5" required> 5 所有交流都可用方言完成</label>

		<p>您是否学习过外国语言(如英语、日语等,不包含中文或汉语方言)?如有,学过多少门?</p>
		<label><input type="radio" name="foreign_language" value="无" required> 无</label>
		<label><input type="radio" name="foreign_language" value="1" required> 1</label>
		<label><input type="radio" name="foreign_language" value="2" required> 2</label>
		<label><input type="radio" name="foreign_language" value="3" required> 3</label>
		<label><input type="radio" name="foreign_language" value="3门以上" required> 3 门以上</label>

		<p>您是否接受过系统的音乐训练(学习乐器/作曲等)?如有,接受训练的时间是?</p>
		<label><input type="radio" name="music_training" value="无" required> 无</label>
		<label><input type="radio" name="music_training" value="1年以下" required> 1 年以下</label>
		<label><input type="radio" name="music_training" value="1-3年" required> 1&ndash;3 年</label>
		<label><input type="radio" name="music_training" value="3-5年" required> 3&ndash;5 年</label>
		<label><input type="radio" name="music_training" value="5-10年" required> 5&ndash;10 年</label>
		<label><input type="radio" name="music_training" value="10年以上" required> 10 年以上</label>

		<p>您是否有绝对音感?</p>
		<label><input type="radio" name="absolute_pitch" value="是" required> 是</label>
		<label><input type="radio" name="absolute_pitch" value="否" required> 否</label>

		<p>您平常听音乐的频率是?</p>
		<label><input type="radio" name="music_freq" value="每天" required> 每天</label>
		<label><input type="radio" name="music_freq" value="每周3-4次" required> 每周 3&ndash;4 次</label>
		<label><input type="radio" name="music_freq" value="每周1-2次" required> 每周 1&ndash;2 次</label>
		<label><input type="radio" name="music_freq" value="每月1-2次" required> 每月 1&ndash;2 次</label>
		<label><input type="radio" name="music_freq" value="几乎不听" required> 几乎不听</label>

		<div class="pagination-buttons">
			<label for="page1">下一页</label>
		</div>
	</div>
	<div class="page page1">
		<div class="pagination-buttons">
			<label for="page0">上一页</label>
		</div>

		<h2>任务 1: 请判断下列音频中的两条旋律/节奏是否相同。</h2>
		<p>音频加载可能需要一些时间。</p>
		<p>请注意,每一个音频只能听一遍。请先调试音量,至少让您能清晰地听见下面的测试音频。</p>
		<table>
			<td>测试音频</td>
			<td><audio controls src="audio/task_2_cadence/learning/Tonic_C.wav"></audio></td>
		</table>
		<h3>旋律辨认测试</h3>
		<table>
			<thead>
				<tr>
					<th>序号</th>
					<th>音频</th>
					<th colspan="2">选项</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>旋律 1</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/01.wav"></audio></td>
					<td><label><input type="radio" name="q1" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q1" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 2</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/02.wav"></audio></td>
					<td><label><input type="radio" name="q2" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q2" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 3</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/03.wav"></audio></td>
					<td><label><input type="radio" name="q3" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q3" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 4</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/04.wav"></audio></td>
					<td><label><input type="radio" name="q4" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q4" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 5</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/05.wav"></audio></td>
					<td><label><input type="radio" name="q5" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q5" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 6</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/06.wav"></audio></td>
					<td><label><input type="radio" name="q6" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q6" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 7</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/07.wav"></audio></td>
					<td><label><input type="radio" name="q7" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q7" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 8</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/08.wav"></audio></td>
					<td><label><input type="radio" name="q8" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q8" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 9</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/09.wav"></audio></td>
					<td><label><input type="radio" name="q9" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q9" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>旋律 10</td>
					<td><audio class="once" controls src="audio/task_1a_pitch_contour/10.wav"></audio></td>
					<td><label><input type="radio" name="q10" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q10" value="不同" required> 不同</label></td>
				</tr>
			</tbody>
		</table>
		<h3>节奏辨认测试</h3>
		<table>
			<thead>
				<tr>
					<th>序号</th>
					<th>音频</th>
					<th colspan="2">选项</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>节奏 1</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/01.wav"></audio></td>
					<td><label><input type="radio" name="q11" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q11" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 2</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/02.wav"></audio></td>
					<td><label><input type="radio" name="q12" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q12" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 3</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/03.wav"></audio></td>
					<td><label><input type="radio" name="q13" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q13" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 4</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/04.wav"></audio></td>
					<td><label><input type="radio" name="q14" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q14" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 5</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/05.wav"></audio></td>
					<td><label><input type="radio" name="q15" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q15" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 6</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/06.wav"></audio></td>
					<td><label><input type="radio" name="q16" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q16" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 7</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/07.wav"></audio></td>
					<td><label><input type="radio" name="q17" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q17" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 8</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/08.wav"></audio></td>
					<td><label><input type="radio" name="q18" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q18" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 9</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/09.wav"></audio></td>
					<td><label><input type="radio" name="q19" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q19" value="不同" required> 不同</label></td>
				</tr>
				<tr>
					<td>节奏 10</td>
					<td><audio class="once" controls src="audio/task_1b_rhythm/10.wav"></audio></td>
					<td><label><input type="radio" name="q20" value="相同" required> 相同</label></td>
					<td><label><input type="radio" name="q20" value="不同" required> 不同</label></td>
				</tr>
			</tbody>
		</table>

		<div class="pagination-buttons">
			<label for="page2">下一页</label>
		</div>
	</div>
	<div class="page page2">
		<div class="pagination-buttons">
			<label for="page1">上一页</label>
		</div>
		<h2>任务 2: 终止式配对</h2>
		<p>请先听 C 大调主和弦并学习 4 种终止式的名称和音响效果。</p>
		<img src="c.png" style="width: 25rem;" />
		<table>
			<tr>
				<td>C大调主和弦</td>
				<td><audio controls src="audio/task_2_cadence/learning/Tonic_C.wav"></audio></td>
			</tr>
			<tr>
				<td>完全终止</td>
				<td><audio controls src="audio/task_2_cadence/learning/V-I.wav"></audio></td>
			</tr>
			<tr>
				<td>变格终止</td>
				<td><audio controls src="audio/task_2_cadence/learning/IV-I.wav"></audio></td>
			</tr>
			<tr>
				<td>导音终止</td>
				<td><audio controls src="audio/task_2_cadence/learning/vii-I.wav"></audio></td>
			</tr>
			<tr>
				<td>阻碍终止</td>
				<td><audio controls src="audio/task_2_cadence/learning/V-vi.wav"></audio></td>
			</tr>
			<thead>
				<tr>
					<th scope="col">终止式</th>
					<th scope="col">音频</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>C大调主和弦</td>
					<td><audio controls src="audio/task_2_cadence/learning/Tonic_C.wav"></audio></td>
				</tr>
				<tr>
					<td>完全终止</td>
					<td><audio controls src="audio/task_2_cadence/learning/V-I.wav"></audio></td>
				</tr>
				<tr>
					<td>变格终止</td>
					<td><audio controls src="audio/task_2_cadence/learning/IV-I.wav"></audio></td>
				</tr>
				<tr>
					<td>导音终止</td>
					<td><audio controls src="audio/task_2_cadence/learning/vii-I.wav"></audio></td>
				</tr>
				<tr>
					<td>阻碍终止</td>
					<td><audio controls src="audio/task_2_cadence/learning/V-vi.wav"></audio></td>
				</tr>
			</tbody>
		</table>
		<p>然后,将在 F♯ 大调上演奏的这 4 种终止式和其名称进行配对。</p>
		<img src="f.png" style="width: 25rem;" />
		<table>
			<tr>
				<td>F♯ 大调主和弦</td>
				<td><audio controls src="audio/task_2_cadence/testing/Tonic_F_sharp.wav"></audio></td>
			</tr>
			<tr>
				<td>1</td>
				<td><audio controls src="audio/task_2_cadence/testing/01.wav"></audio></td>
			</tr>
			<tr>
				<td>2</td>
				<td><audio controls src="audio/task_2_cadence/testing/02.wav"></audio></td>
			</tr>
			<tr>
				<td>3</td>
				<td><audio controls src="audio/task_2_cadence/testing/03.wav"></audio></td>
			</tr>
			<tr>
				<td>4</td>
				<td><audio controls src="audio/task_2_cadence/testing/04.wav"></audio></td>
			</tr>
			<thead>
				<tr>
					<th scope="col">序号</th>
					<th scope="col">音频</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>F♯ 大调主和弦</td>
					<td><audio controls src="audio/task_2_cadence/testing/Tonic_F_sharp.wav"></audio></td>
				</tr>
				<tr>
					<td>1</td>
					<td><audio controls src="audio/task_2_cadence/testing/01.wav"></audio></td>
				</tr>
				<tr>
					<td>2</td>
					<td><audio controls src="audio/task_2_cadence/testing/02.wav"></audio></td>
				</tr>
				<tr>
					<td>3</td>
					<td><audio controls src="audio/task_2_cadence/testing/03.wav"></audio></td>
				</tr>
				<tr>
					<td>4</td>
					<td><audio controls src="audio/task_2_cadence/testing/04.wav"></audio></td>
				</tr>
			</tbody>
		</table>
		<p>请将以上终止式音频的数字序号填入其相对应的终止式序号。</p>
		<table>
			<tr><td><label style="margin: 0;">完全终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence1" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">变格终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence2" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">导音终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence3" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">阻碍终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence4" placeholder="请填写序号" required></td></tr>
			<thead>
				<tr>
					<th scope="col">终止式</th>
					<th scope="col">对应序号?</th>
				</tr>
			</thead>
			<tbody>
				<tr><td><label style="margin: 0;">完全终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence1" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">变格终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence2" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">导音终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence3" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">阻碍终止</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="cadence4" placeholder="请填写序号" required></td></tr>
			</tbody>
		</table>
		<div class="pagination-buttons">
			<label for="page3">下一页</label>
		</div>
	</div>
	<div class="page page3">
		<div class="pagination-buttons">
			<label for="page2">上一页</label>
		</div>
		<h2>任务 3: 音乐风格识别</h2>
		<p>请聆听并学习 5 种音乐风格的鼓组节奏型和音色特点。</p>
		<table>
			<tr>
				<td>Trap 陷阱</td>
				<td><audio controls src="audio/task_3_drum_pattern/learning/trap.wav"></audio></td>
			</tr>
			<tr>
				<td>Drill 钻头</td>
				<td><audio controls src="audio/task_3_drum_pattern/learning/drill.wav"></audio></td>
			</tr>
			<tr>
				<td>Drum &amp; Bass 鼓与贝斯</td>
				<td><audio controls src="audio/task_3_drum_pattern/learning/drum_and_bass.wav"></audio></td>
			</tr>
			<tr>
				<td>Reggaetton 雷击顿</td>
				<td><audio controls src="audio/task_3_drum_pattern/learning/reggaeton.wav"></audio></td>
			</tr>
			<tr>
				<td>R&amp;B 节奏蓝调</td>
				<td><audio controls src="audio/task_3_drum_pattern/learning/r_and_b.wav"></audio></td>
			</tr>
			<thead>
				<tr>
				<th scope="col">风格</th>
				<th scope="col">音频样本</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>Trap 陷阱</td>
					<td><audio controls src="audio/task_3_drum_pattern/learning/trap.wav"></audio></td>
				</tr>
				<tr>
					<td>Drill 钻头</td>
					<td><audio controls src="audio/task_3_drum_pattern/learning/drill.wav"></audio></td>
				</tr>
				<tr>
					<td>Drum &amp; Bass 鼓与贝斯</td>
					<td><audio controls src="audio/task_3_drum_pattern/learning/drum_and_bass.wav"></audio></td>
				</tr>
				<tr>
					<td>Reggaetton 雷击顿</td>
					<td><audio controls src="audio/task_3_drum_pattern/learning/reggaeton.wav"></audio></td>
				</tr>
				<tr>
					<td>R&amp;B 节奏蓝调</td>
					<td><audio controls src="audio/task_3_drum_pattern/learning/r_and_b.wav"></audio></td>
				</tr>
			</tbody>
		</table>

		<p>然后,将 5 个真实音乐片段与其风格相对应。</p>
		<table>
			<tr>
				<td>1</td>
				<td><audio controls src="audio/task_3_drum_pattern/testing/01.wav"></audio></td>
			</tr>
			<tr>
				<td>2</td>
				<td><audio controls src="audio/task_3_drum_pattern/testing/02.wav"></audio></td>
			</tr>
			<tr>
				<td>3</td>
				<td><audio controls src="audio/task_3_drum_pattern/testing/03.wav"></audio></td>
			</tr>
			<tr>
				<td>4</td>
				<td><audio controls src="audio/task_3_drum_pattern/testing/04.wav"></audio></td>
			</tr>
			<tr>
				<td>5</td>
				<td><audio controls src="audio/task_3_drum_pattern/testing/05.wav"></audio></td>
			</tr>
			<thead>
				<tr>
					<th scope="col">序号</th>
					<th scope="col">真实片段音频</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>1</td>
					<td><audio controls src="audio/task_3_drum_pattern/testing/01.wav"></audio></td>
				</tr>
				<tr>
					<td>2</td>
					<td><audio controls src="audio/task_3_drum_pattern/testing/02.wav"></audio></td>
				</tr>
				<tr>
					<td>3</td>
					<td><audio controls src="audio/task_3_drum_pattern/testing/03.wav"></audio></td>
				</tr>
				<tr>
					<td>4</td>
					<td><audio controls src="audio/task_3_drum_pattern/testing/04.wav"></audio></td>
				</tr>
				<tr>
					<td>5</td>
					<td><audio controls src="audio/task_3_drum_pattern/testing/05.wav"></audio></td>
				</tr>
			</tbody>
		</table>


		<p>请将以上片段的序号与其风格相对应(只填阿拉伯数字)。</p>
		<table>
			<tr><td><label style="margin: 0;">Trap 陷阱</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style1trap" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">Drill 钻头</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style2drill" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">Drum &amp; Bass 鼓与贝斯</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style3drumbass" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">Reggaetton 雷击顿</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style4reggaetton" placeholder="请填写序号" required></td></tr>
			<tr><td><label style="margin: 0;">R&amp;B 节奏蓝调</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style5rb" placeholder="请填写序号" required></td></tr>
			<thead>
				<tr>
					<th scope="col">风格</th>
					<th scope="col">对应序号?</th>
				</tr>
			</thead>
			<tbody>
				<tr><td><label style="margin: 0;">Trap 陷阱</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style1trap" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">Drill 钻头</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style2drill" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">Drum &amp; Bass 鼓与贝斯</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style3drumbass" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">Reggaetton 雷击顿</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style4reggaetton" placeholder="请填写序号" required></td></tr>
				<tr><td><label style="margin: 0;">R&amp;B 节奏蓝调</label></td><td><input style="padding: 0.5rem 0.4rem;" type="text" name="style5rb" placeholder="请填写序号" required></td></tr>
			</tbody>
		</table>

		<p>恭喜您完成所有测试并衷心感谢您的参与!</p>
		<p>如有兴趣了解实验数据分析结果,请关注微信公众号 @WIT studio。</p>

	<button type="submit">提交</button>

	<p>
	如果您无法提交,可能是因为有些问题没有完成。在这种情况下,请 <label for="show-all-pages" class="show-all-pages-label">显示所有页面</label>,然后再点提交的时候,浏览器就能告诉你问题出在哪里了。
	</p>

</div>
	</div>
	</form>
	</div>
</body>
</html>