Spaces:
Runtime error
Runtime error
Update templates/index.html
Browse files- templates/index.html +67 -47
templates/index.html
CHANGED
|
@@ -166,19 +166,13 @@
|
|
| 166 |
let recordingInterval;
|
| 167 |
let count_voice = 0;
|
| 168 |
let before_rate = [];
|
| 169 |
-
const RECORDING_INTERVAL_MS = 1000; //
|
|
|
|
| 170 |
// メンバーとチャートの初期化
|
| 171 |
let members = [];
|
| 172 |
let voiceData = [];
|
| 173 |
-
let baseMemberColors = [
|
| 174 |
-
|
| 175 |
-
"#007bff",
|
| 176 |
-
"#ffc107",
|
| 177 |
-
"#dc3545",
|
| 178 |
-
"#28a745",
|
| 179 |
-
"#9c27b0",
|
| 180 |
-
"#ff9800",
|
| 181 |
-
];
|
| 182 |
// Chart.js の初期化
|
| 183 |
const ctx = document.getElementById("speechChart").getContext("2d");
|
| 184 |
const speechChart = new Chart(ctx, {
|
|
@@ -203,6 +197,7 @@
|
|
| 203 |
},
|
| 204 |
},
|
| 205 |
});
|
|
|
|
| 206 |
// サーバーからメンバー情報を取得してチャートを更新する関数
|
| 207 |
async function updateChartFrom() {
|
| 208 |
try {
|
|
@@ -211,6 +206,7 @@
|
|
| 211 |
throw new Error(`HTTP error! status: ${response.status}`);
|
| 212 |
}
|
| 213 |
const data = await response.json();
|
|
|
|
| 214 |
if (!data || !data.members || !Array.isArray(data.members)) {
|
| 215 |
console.error("Invalid member data received:", data);
|
| 216 |
members = ["member1"];
|
|
@@ -218,11 +214,13 @@
|
|
| 218 |
updateChart();
|
| 219 |
return;
|
| 220 |
}
|
|
|
|
| 221 |
members = data.members;
|
| 222 |
voiceData = [];
|
| 223 |
for (let i = 0; i < members.length; i++) {
|
| 224 |
voiceData.push(100 / members.length);
|
| 225 |
}
|
|
|
|
| 226 |
updateChart();
|
| 227 |
} catch (error) {
|
| 228 |
console.error("Failed to fetch member data:", error);
|
|
@@ -231,6 +229,7 @@
|
|
| 231 |
updateChart();
|
| 232 |
}
|
| 233 |
}
|
|
|
|
| 234 |
function updateChart() {
|
| 235 |
// 一人モードの場合は、ユーザーとグレー(無音)の比率をチャートに表示
|
| 236 |
if (members.length === 1) {
|
|
@@ -240,37 +239,40 @@
|
|
| 240 |
} else {
|
| 241 |
// 複数メンバーの場合は通常通りの処理
|
| 242 |
speechChart.data.labels = members;
|
| 243 |
-
speechChart.data.datasets[0].backgroundColor = getMemberColors(
|
| 244 |
-
members.length
|
| 245 |
-
);
|
| 246 |
}
|
|
|
|
| 247 |
speechChart.data.datasets[0].data = voiceData;
|
| 248 |
speechChart.update();
|
| 249 |
}
|
|
|
|
| 250 |
// ページ読み込み時にチャート情報を更新
|
| 251 |
updateChartFrom();
|
|
|
|
| 252 |
// 録音ボタンの録音開始/停止処理
|
| 253 |
async function toggleRecording() {
|
| 254 |
const recordButton = document.getElementById("recordButton");
|
|
|
|
| 255 |
if (!isRecording) {
|
| 256 |
// 録音開始
|
| 257 |
isRecording = true;
|
| 258 |
recordButton.classList.add("recording");
|
| 259 |
try {
|
| 260 |
-
const stream = await navigator.mediaDevices.getUserMedia({
|
| 261 |
-
audio: true,
|
| 262 |
-
});
|
| 263 |
mediaRecorder = new MediaRecorder(stream);
|
| 264 |
audioChunks = [];
|
|
|
|
| 265 |
mediaRecorder.ondataavailable = (event) => {
|
| 266 |
if (event.data.size > 0) {
|
| 267 |
audioChunks.push(event.data);
|
| 268 |
}
|
| 269 |
};
|
|
|
|
| 270 |
mediaRecorder.onstop = () => {
|
| 271 |
sendAudioChunks([...audioChunks]);
|
| 272 |
audioChunks = [];
|
| 273 |
};
|
|
|
|
| 274 |
mediaRecorder.start();
|
| 275 |
// 5秒ごとに録音を停止して送信するインターバルを設定
|
| 276 |
recordingInterval = setInterval(() => {
|
|
@@ -296,6 +298,7 @@
|
|
| 296 |
before_rate = [];
|
| 297 |
}
|
| 298 |
}
|
|
|
|
| 299 |
function sendAudioChunks(chunks) {
|
| 300 |
const audioBlob = new Blob(chunks, { type: "audio/wav" });
|
| 301 |
const reader = new FileReader();
|
|
@@ -326,6 +329,7 @@
|
|
| 326 |
};
|
| 327 |
reader.readAsDataURL(audioBlob);
|
| 328 |
}
|
|
|
|
| 329 |
function getMemberColors(memberCount) {
|
| 330 |
// 一人モードの場合は特別な処理をしない(updateChartで処理するため)
|
| 331 |
if (memberCount <= 1) {
|
|
@@ -338,6 +342,7 @@
|
|
| 338 |
return colors;
|
| 339 |
}
|
| 340 |
}
|
|
|
|
| 341 |
function updateChartData(newRate) {
|
| 342 |
// 一人モードの時の処理
|
| 343 |
if (members.length === 1) {
|
|
@@ -346,56 +351,71 @@
|
|
| 346 |
before_rate = [newRate];
|
| 347 |
} else {
|
| 348 |
// 一人モードでは、過去のデータと現在のデータを加重平均する
|
| 349 |
-
let tmp_rate =
|
| 350 |
-
(newRate + before_rate[0] * count_voice) / (count_voice + 1);
|
| 351 |
speechChart.data.datasets[0].data = [tmp_rate, 100 - tmp_rate];
|
| 352 |
before_rate = [tmp_rate];
|
| 353 |
}
|
| 354 |
count_voice++;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
} else {
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
|
|
|
| 360 |
}
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
}
|
| 365 |
-
updateChart();
|
| 366 |
-
}
|
| 367 |
-
}
|
| 368 |
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
menu.classList.toggle("open");
|
| 374 |
-
}
|
| 375 |
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
}
|
| 382 |
-
}
|
| 383 |
|
| 384 |
-
|
| 385 |
-
function showUserRegister() {
|
| 386 |
-
console.log("ユーザー登録画面を表示");
|
| 387 |
}
|
| 388 |
|
| 389 |
function showTalkdetail() {
|
| 390 |
-
|
| 391 |
}
|
| 392 |
|
| 393 |
function showResults() {
|
| 394 |
-
|
| 395 |
}
|
| 396 |
|
| 397 |
-
function
|
| 398 |
-
|
|
|
|
| 399 |
}
|
| 400 |
</script>
|
| 401 |
</body>
|
|
|
|
| 166 |
let recordingInterval;
|
| 167 |
let count_voice = 0;
|
| 168 |
let before_rate = [];
|
| 169 |
+
const RECORDING_INTERVAL_MS = 1000; // 5秒
|
| 170 |
+
|
| 171 |
// メンバーとチャートの初期化
|
| 172 |
let members = [];
|
| 173 |
let voiceData = [];
|
| 174 |
+
let baseMemberColors = ["#4caf50", "#007bff", "#ffc107", "#dc3545", "#28a745", "#9c27b0", "#ff9800"];
|
| 175 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
// Chart.js の初期化
|
| 177 |
const ctx = document.getElementById("speechChart").getContext("2d");
|
| 178 |
const speechChart = new Chart(ctx, {
|
|
|
|
| 197 |
},
|
| 198 |
},
|
| 199 |
});
|
| 200 |
+
|
| 201 |
// サーバーからメンバー情報を取得してチャートを更新する関数
|
| 202 |
async function updateChartFrom() {
|
| 203 |
try {
|
|
|
|
| 206 |
throw new Error(`HTTP error! status: ${response.status}`);
|
| 207 |
}
|
| 208 |
const data = await response.json();
|
| 209 |
+
|
| 210 |
if (!data || !data.members || !Array.isArray(data.members)) {
|
| 211 |
console.error("Invalid member data received:", data);
|
| 212 |
members = ["member1"];
|
|
|
|
| 214 |
updateChart();
|
| 215 |
return;
|
| 216 |
}
|
| 217 |
+
|
| 218 |
members = data.members;
|
| 219 |
voiceData = [];
|
| 220 |
for (let i = 0; i < members.length; i++) {
|
| 221 |
voiceData.push(100 / members.length);
|
| 222 |
}
|
| 223 |
+
|
| 224 |
updateChart();
|
| 225 |
} catch (error) {
|
| 226 |
console.error("Failed to fetch member data:", error);
|
|
|
|
| 229 |
updateChart();
|
| 230 |
}
|
| 231 |
}
|
| 232 |
+
|
| 233 |
function updateChart() {
|
| 234 |
// 一人モードの場合は、ユーザーとグレー(無音)の比率をチャートに表示
|
| 235 |
if (members.length === 1) {
|
|
|
|
| 239 |
} else {
|
| 240 |
// 複数メンバーの場合は通常通りの処理
|
| 241 |
speechChart.data.labels = members;
|
| 242 |
+
speechChart.data.datasets[0].backgroundColor = getMemberColors(members.length);
|
|
|
|
|
|
|
| 243 |
}
|
| 244 |
+
|
| 245 |
speechChart.data.datasets[0].data = voiceData;
|
| 246 |
speechChart.update();
|
| 247 |
}
|
| 248 |
+
|
| 249 |
// ページ読み込み時にチャート情報を更新
|
| 250 |
updateChartFrom();
|
| 251 |
+
|
| 252 |
// 録音ボタンの録音開始/停止処理
|
| 253 |
async function toggleRecording() {
|
| 254 |
const recordButton = document.getElementById("recordButton");
|
| 255 |
+
|
| 256 |
if (!isRecording) {
|
| 257 |
// 録音開始
|
| 258 |
isRecording = true;
|
| 259 |
recordButton.classList.add("recording");
|
| 260 |
try {
|
| 261 |
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
|
|
|
|
|
| 262 |
mediaRecorder = new MediaRecorder(stream);
|
| 263 |
audioChunks = [];
|
| 264 |
+
|
| 265 |
mediaRecorder.ondataavailable = (event) => {
|
| 266 |
if (event.data.size > 0) {
|
| 267 |
audioChunks.push(event.data);
|
| 268 |
}
|
| 269 |
};
|
| 270 |
+
|
| 271 |
mediaRecorder.onstop = () => {
|
| 272 |
sendAudioChunks([...audioChunks]);
|
| 273 |
audioChunks = [];
|
| 274 |
};
|
| 275 |
+
|
| 276 |
mediaRecorder.start();
|
| 277 |
// 5秒ごとに録音を停止して送信するインターバルを設定
|
| 278 |
recordingInterval = setInterval(() => {
|
|
|
|
| 298 |
before_rate = [];
|
| 299 |
}
|
| 300 |
}
|
| 301 |
+
|
| 302 |
function sendAudioChunks(chunks) {
|
| 303 |
const audioBlob = new Blob(chunks, { type: "audio/wav" });
|
| 304 |
const reader = new FileReader();
|
|
|
|
| 329 |
};
|
| 330 |
reader.readAsDataURL(audioBlob);
|
| 331 |
}
|
| 332 |
+
|
| 333 |
function getMemberColors(memberCount) {
|
| 334 |
// 一人モードの場合は特別な処理をしない(updateChartで処理するため)
|
| 335 |
if (memberCount <= 1) {
|
|
|
|
| 342 |
return colors;
|
| 343 |
}
|
| 344 |
}
|
| 345 |
+
|
| 346 |
function updateChartData(newRate) {
|
| 347 |
// 一人モードの時の処理
|
| 348 |
if (members.length === 1) {
|
|
|
|
| 351 |
before_rate = [newRate];
|
| 352 |
} else {
|
| 353 |
// 一人モードでは、過去のデータと現在のデータを加重平均する
|
| 354 |
+
let tmp_rate = (newRate + before_rate[0] * count_voice) / (count_voice + 1);
|
|
|
|
| 355 |
speechChart.data.datasets[0].data = [tmp_rate, 100 - tmp_rate];
|
| 356 |
before_rate = [tmp_rate];
|
| 357 |
}
|
| 358 |
count_voice++;
|
| 359 |
+
|
| 360 |
+
// 一人モードでは常に緑色とグレーの組み合わせを使用
|
| 361 |
+
speechChart.data.labels = [members[0], "無音"];
|
| 362 |
+
speechChart.data.datasets[0].backgroundColor = ["#4caf50", "#757575"];
|
| 363 |
} else {
|
| 364 |
+
console.log(before_rate)
|
| 365 |
+
// 複数人モードの処理
|
| 366 |
+
if (!Array.isArray(newRate)) {
|
| 367 |
+
console.error("newRate is not an array:", newRate);
|
| 368 |
+
return;
|
| 369 |
}
|
| 370 |
+
if (newRate.length !== members.length) {
|
| 371 |
+
console.error(
|
| 372 |
+
"newRate length does not match members length:",
|
| 373 |
+
newRate,
|
| 374 |
+
members
|
| 375 |
+
);
|
| 376 |
+
return;
|
| 377 |
}
|
|
|
|
|
|
|
|
|
|
| 378 |
|
| 379 |
+
let averagedRates = new Array(newRate.length);
|
| 380 |
+
|
| 381 |
+
for (let i = 0; i < newRate.length; i++) {
|
| 382 |
+
let tmp_rate;
|
|
|
|
|
|
|
| 383 |
|
| 384 |
+
if (count_voice === 0) {
|
| 385 |
+
// 初回はそのまま
|
| 386 |
+
tmp_rate = newRate[i];
|
| 387 |
+
} else {
|
| 388 |
+
// 2回目以降は、過去の平均値と現在の値を加重平均する
|
| 389 |
+
tmp_rate = (newRate[i] + before_rate[i] * count_voice) / (count_voice + 1);
|
| 390 |
+
}
|
| 391 |
+
averagedRates[i] = tmp_rate;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
// before_rateを更新
|
| 395 |
+
before_rate = averagedRates;
|
| 396 |
+
|
| 397 |
+
//グラフに反映
|
| 398 |
+
speechChart.data.datasets[0].data = averagedRates;
|
| 399 |
+
count_voice++;
|
| 400 |
+
speechChart.data.datasets[0].backgroundColor = getMemberColors(
|
| 401 |
+
members.length
|
| 402 |
+
);
|
| 403 |
}
|
|
|
|
| 404 |
|
| 405 |
+
speechChart.update();
|
|
|
|
|
|
|
| 406 |
}
|
| 407 |
|
| 408 |
function showTalkdetail() {
|
| 409 |
+
window.location.href = "talk_detail";
|
| 410 |
}
|
| 411 |
|
| 412 |
function showResults() {
|
| 413 |
+
window.location.href = "feedback";
|
| 414 |
}
|
| 415 |
|
| 416 |
+
function showUserRegister() {
|
| 417 |
+
fetch("/reset");
|
| 418 |
+
window.location.href = "userregister";
|
| 419 |
}
|
| 420 |
</script>
|
| 421 |
</body>
|